<?php

namespace app\admin\service;

use EasyFeiShu\Contact\Contact;
use EasyFeiShu\Foundation\Application;
use EasyFeiShu\User\AccessToken;
use Overtrue\Socialite\SocialiteManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use think\admin\extend\HttpExtend;
use think\admin\Service;
use think\cache\driver\Redis;
use think\facade\Db;
use think\facade\Log;

/**
 * 飞书服务
 * Class FeiShuService
 * @package app\data\service
 */
class FeiShuService extends Service
{
    protected $config;

    /**
     * @var Contact
     */
    protected $contacts;

    /**
     * @var Application
     */
    protected $feiShuApp;

    protected function initialize()
    {
        $this->config = config('fei_shu');
        $this->config = [
            'debug' => true,
            'app_id' => $this->config['applications']['default']['app_id'],
            'app_secret' => $this->config['applications']['default']['app_secret'],
            'encrypt_key' => $this->config['applications']['default']['encrypt_key'],
            'verification_token' => '',
            'cache' => new Redis(),
            'log' => [
                'file' => app()->getRuntimePath() . 'fei_shu_log/' . date('Y-m-d') . '.log',
                'level' => 'debug',
            ],
        ];

        $this->feiShuApp = new Application($this->config);
        $this->contacts = $this->feiShuApp->contact;
    }

    /**
     * 事件回调
     * @return \EasyFeiShu\Server\Guard
     */
    public function server()
    {
        return $this->feiShuApp->server;
    }


    /**
     * 获取部门ID列表
     * @return void
     */
    public function departmentList()
    {
        $pageToken = '';

        while (isset($pageToken)) {

            // 批量获取子部门列表
            $departmentList = $this->contacts->getDepartmentsChildren(0, [
                'user_id_type' => 'open_id',
                'department_id_type' => 'open_department_id',
                'department_id' => 0,
                'fetch_child' => true,
                'page_size' => 50,
                'page_token' => $pageToken
            ]);
            unset($pageToken);

            if (!empty($departmentList['data']['page_token'])) {
                $pageToken = $departmentList['data']['page_token'];
            }

            foreach ($departmentList['data']['items'] ?? [] as $department) {
                $departmentInsertData[] = [
                    'parent_department_id' => $department['parent_department_id'],
                    'open_department_id' => $department['open_department_id'],
                    'name' => $department['name'],
                    'order' => $department['order'],
                ];
            }
        }

        if (!empty($departmentInsertData)) {
            Db::execute('TRUNCATE TABLE `work_department`');
            $this->app->db->name('work_department')->insertAll($departmentInsertData);
        }
    }

    /**
     * 获取用户列表
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function userList()
    {
        $this->getUserDetailedDepartmentUsers('');
        $departments = $this->app->db->name('work_department')->select()->toArray();
        foreach ($departments as $department) {
            $this->getUserDetailedDepartmentUsers($department['open_department_id']);
        }
    }

    /**
     * 删除部门
     * @param $id
     * @return void
     * @throws \think\db\exception\DbException
     */
    public function deleteDepartment($openDepartmentId)
    {
        $this->app->db->name('work_department')->where('open_department_id', $openDepartmentId)->delete();
    }

    /**
     * 获取员工列表数据
     * @param $contacts
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getUserDetailedDepartmentUsers($departmentId)
    {
        $pageToken = '';

        while (isset($pageToken)) {
            $users = $this->contacts->findByDepartment([
                'user_id_type' => 'open_id',
                'department_id_type' => 'open_department_id',
                'department_id' => $departmentId,
                'page_size' => 50,
                'page_token' => $pageToken
            ]);

            unset($pageToken);

            if (!empty($departmentList['page_token'])) {
                $pageToken = $departmentList['page_token'];
            }

            $unionIds = array_column($users['data']['items'] ?? [], 'union_id');
            $existUnionIds = $this->app->db->name('work_user')->whereIn('union_id', $unionIds)->select()->toArray();
            $existUnionIds = array_column($existUnionIds, 'union_id');

            foreach ($users['data']['items'] ?? [] as $user) {
                $data = [
                    'union_id' => $user['union_id'],
                    'user_id' => $user['user_id'],
                    'open_id' => $user['open_id'],
                    'name' => $user['name'],
                    'username' => str_replace('+86', '', $user['mobile']),
                    'department_ids'  => implode(',', $user['department_ids']),
                    'mobile'         => $user['mobile'],
                    'is_deleted'         => 0,
                ];
                if (!empty($user['avatar']['avatar_origin'])) {
                    $data['avatar'] = $user['avatar']['avatar_origin'];
                }

                if (in_array($user['union_id'], $existUnionIds)) {
                    $updateUpdateData[] = $data;
                } else {
                    $data['password'] = md5(str_replace('+86', '', $user['mobile']));
                    $userInsertData[] = $data;
                }
            }
        }

        if (!empty($userInsertData)) {
            $this->app->db->name('work_user')->insertAll($userInsertData);
        }
        if (!empty($updateUpdateData)) {
            foreach ($updateUpdateData as $updateUpdateDataItem) {
                $this->app->db->name('work_user')->where('union_id', $updateUpdateDataItem['union_id'])->update($updateUpdateDataItem);
            }
        }

    }

    /**
     * 删除员工
     * @param $userid
     * @return void
     * @throws \think\db\exception\DbException
     */
    public function deleteUser($openId)
    {
        if (!empty($openId)) {
            $this->app->db->name('work_user')->where('open_id', $openId)->update(['status' => 5]);
        }
    }

    /**
     * 更新用户
     * @param $user
     * @return void
     * @throws \think\db\exception\DbException
     */
    public function updateUser($user)
    {
        $data = [
            'union_id' => $user['union_id'],
            'user_id' => $user['user_id'],
            'open_id' => $user['open_id'],
            'username' => str_replace('+86', '', $user['mobile']),
            'name' => $user['name'],
            'department_ids'  => implode(',', $user['department_ids']),
            'mobile'         => $user['mobile'],
            'is_deleted'         => 0,
        ];
        if (!empty($user['avatar']['avatar_origin'])) {
            $data['avatar'] = $user['avatar']['avatar_origin'];
        }

        $dbUser = $this->app->db->name('work_user')->where('union_id', $user['union_id'])->findOrEmpty();
        if ($dbUser) {
            $this->app->db->name('work_user')->where('union_id', $user['union_id'])->update($data);
        } else {
            $data['password'] = md5(str_replace('+86', '', $data['mobile']));
            $this->app->db->name('work_user')->insert($data);
        }
    }

    /**
     * 发送消息
     * @param $openId
     * @param $message
     * @return \Supports\Collection
     */
    public function sendMessageTextByUserid($openId, $message)
    {
        if (env('APP_DEBUG')) {
            return true;
        }

        // 发送
        $params = [
            'receive_id' => $openId,
            'msg_type' => 'text',
            'content' => json_encode([
                'text' => $message
            ], JSON_UNESCAPED_UNICODE),
        ];
        $result = $this->feiShuApp->im->postMessages($params);

        if (!empty($result['code'])) {
            Log::error('飞书发送消息失败 ' . json_encode($result));
        }

        return $result;
    }

    /**
     * 获取打卡日报数据
     */
    public function checkInRecords(int $startTime, int $endTime, array $user)
    {
        try {
            $params = [
                'user_ids' => $user,
                'check_time_from' => $startTime,
                'check_time_to' => $endTime,
            ];
            $result = $this->feiShuApp->userFlow->userStatsData($params);

            $checkInUsers = array_column($result['data']['user_flow_results'] ?? [], 'user_id');
        } catch (\Exception $exception) {
            Log::error('获取打卡信息失败' . $exception->getMessage());
        }

        return array_unique($checkInUsers ?? []);
    }

    /**
     * 授权登录回调
     */
    public function oauthRedirect()
    {
        // $callbackUrl 为授权回调地址
        $callbackUrl = getHttpHost(true); // 需设置可信域名
        $callbackUrl = urlencode($callbackUrl);

        // 返回一个 redirect 实例
        $url = getHttpHost() . "/admin/api.FeiShu/oauthCallback?callback=" . $callbackUrl;

        $this->config = config('fei_shu');

        $url = $this->feiShuApp->authen->authorize($this->config['applications']['default']['app_id'], $url);

        // 创建一个 RedirectResponse 对象进行重定向
        $redirectResponse = new RedirectResponse($url);
        $redirectContent = $redirectResponse->getContent();

        $response = new Response($redirectContent, 200);
        $response->send();
    }

    /**
     * 返回授权的userid
     * @return mixed|string|null
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \Overtrue\Socialite\Exceptions\AuthorizeFailedException
     */
    public function getOpenId()
    {
        $code = request()->get('code', '');
        $userAccessToken = $this->feiShuApp->authen->userAccessToken($code);
        $userAccessToken = $userAccessToken['data']['access_token'] ?? '';

        $userInfo = new $this->feiShuApp->user->authen(new AccessToken($userAccessToken));
        $userInfo = $userInfo->userInfo();

        return $userInfo['data']['open_id'] ?? '';
    }
}